#include <stdio.h>
#include <stdarg.h>
#include "omx_osa_posix.h"
#include "omx_comp_debug_levels.h"

int omx_thread_create(omx_thread *tid, const omx_thread_attr *attr, void *(*start)(void*), void *arg)
{
    return pthread_create(tid, attr, start, arg);
}

/**************************************************************************/
/*                                                                        */
/**************************************************************************/

int omx_thread_join(omx_thread *thread, void **value_ptr)
{
    return pthread_join(*thread, value_ptr);
}

/**************************************************************************/
/*                                                                        */
/**************************************************************************/

int omx_thread_cancel(omx_thread *threadId)
{
    return pthread_cancel(*threadId);
}

/**************************************************************************/
/*                                                                        */
/**************************************************************************/

int omx_thread_mutex_init(omx_thread_mutex *mutex, const omx_thread_mutexattr *attr)
{
    return pthread_mutex_init(mutex, attr);
}

/**************************************************************************/
/*                                                                        */
/**************************************************************************/

int omx_thread_mutex_lock(omx_thread_mutex *mutex)
{
    return pthread_mutex_lock(mutex);
}

/**************************************************************************/
/*                                                                        */
/**************************************************************************/

int omx_thread_mutex_unlock(omx_thread_mutex *mutex)
{
    return pthread_mutex_unlock(mutex);

}

/**************************************************************************/
/*                                                                        */
/**************************************************************************/

int omx_thread_mutex_destroy(omx_thread_mutex *mutex)
{
    return pthread_mutex_destroy(mutex);
}

/**************************************************************************/
/*                                                                        */
/**************************************************************************/

int omx_thread_cond_wait(omx_thread_cond *cond, omx_thread_mutex *mutex)
{
    return pthread_cond_wait(cond, mutex);
}

/**************************************************************************/
/*                                                                        */
/**************************************************************************/

int omx_thread_cond_signal(omx_thread_cond *cond)
{
    return pthread_cond_signal(cond);
}

/**************************************************************************/
/*                                                                        */
/**************************************************************************/

int omx_thread_cond_init(omx_thread_cond *cond, const omx_thread_condattr *attr)
{
    return pthread_cond_init(cond, attr);
}

/**************************************************************************/
/*                                                                        */
/**************************************************************************/

int omx_thread_cond_destroy(omx_thread_cond *cond)
{
    return pthread_cond_destroy(cond);
}

/**************************************************************************/
/*                                                                        */
/**************************************************************************/

int omx_usleep(unsigned int time)
{
#ifdef WIN32
    _sleep(time / 1000);
#else
    usleep(time);
#endif
    return 0;

}

/**************************************************************************/
/*                                                                        */
/**************************************************************************/

void omx_sem_init(omx_sem *tsem, unsigned int val)
{
    omx_thread_cond_init(&tsem->condition, NULL);
    omx_thread_mutex_init(&tsem->mutex, NULL);
    tsem->semval = val;
}

/** Destroy the semaphore
 *
 * @param tsem the semaphore to destroy
 */
void omx_sem_deinit(omx_sem *tsem)
{
    omx_thread_cond_destroy(&tsem->condition);
    omx_thread_mutex_destroy(&tsem->mutex);
}

/** Decreases the value of the semaphore. Blocks if the semaphore
 * value is zero.
 *
 * @param tsem the semaphore to decrease
 */
void omx_sem_down(omx_sem *tsem)
{
    omx_thread_mutex_lock(&tsem->mutex);
    while (tsem->semval == 0)
    {
        omx_thread_cond_wait(&tsem->condition, &tsem->mutex);
    }
    tsem->semval--;
    omx_thread_mutex_unlock(&tsem->mutex);
}

/** Increases the value of the semaphore
 *
 * @param tsem the semaphore to increase
 */
void omx_sem_up(omx_sem *tsem)
{
    omx_thread_mutex_lock(&tsem->mutex);
    tsem->semval++;
    omx_thread_cond_signal(&tsem->condition);
    omx_thread_mutex_unlock(&tsem->mutex);
}

/** Reset the value of the semaphore
 *
 * @param tsem the semaphore to reset
 */
void omx_sem_reset(omx_sem *tsem)
{
    omx_thread_mutex_lock(&tsem->mutex);
    tsem->semval = 0;
    omx_thread_mutex_unlock(&tsem->mutex);
}

/** Wait on the condition.
 *
 * @param tsem the semaphore to wait
 */
void omx_sem_wait(omx_sem *tsem)
{
    omx_thread_mutex_lock(&tsem->mutex);
    omx_thread_cond_wait(&tsem->condition, &tsem->mutex);
    omx_thread_mutex_unlock(&tsem->mutex);
}

/** Signal the condition,if waiting
 *
 * @param tsem the semaphore to signal
 */
void omx_sem_signal(omx_sem *tsem)
{
    omx_thread_mutex_lock(&tsem->mutex);
    omx_thread_cond_signal(&tsem->condition);
    omx_thread_mutex_unlock(&tsem->mutex);
}

/**************************************************************************/
/*                                                                        */
/**************************************************************************/

int omx_sem_count(omx_sem *tsem)
{
    return tsem->semval;
}

/**************************************************************************/
/*                                                                        */
/**************************************************************************/

#ifdef MEM_LEAK_DETECTIVE
static unsigned int HeapAllocCount = 0;
#endif

void *omx_malloc(unsigned int size)
{
#ifdef MEM_LEAK_DETECTIVE
    HeapAllocCount++;
#endif

    return (void*)malloc(size);

}

/**************************************************************************/
/*                                                                        */
/**************************************************************************/

void *omx_calloc(unsigned int nBlock, size_t size)
{
#ifdef MEM_LEAK_DETECTIVE
    HeapAllocCount++;
#endif
    return (void*)calloc(nBlock, size);
}

/**************************************************************************/
/*                                                                        */
/**************************************************************************/

unsigned int omx_free(void *mem_ptr)
{
#ifdef MEM_LEAK_DETECTIVE
    HeapAllocCount--;
    DEBUG(255, "Mem remain for release %d\n", HeapAllocCount);
#endif

    free(mem_ptr);
    return 0;
}

/**************************************************************************/
/*                                                                        */
/**************************************************************************/

omx_file *omx_file_open(const char *filename, const char *mode)
{
    return fopen(filename, mode);
}

/**************************************************************************/
/*                                                                        */
/**************************************************************************/

void omx_file_close(omx_file *handle)
{
    fclose(handle);
}

/**************************************************************************/
/*                                                                        */
/**************************************************************************/

unsigned int omx_file_read(void *buffer, unsigned int nBlock, unsigned int size, omx_file *filehandle)
{
    return fread(buffer, nBlock, size, filehandle);
}

/**************************************************************************/
/*                                                                        */
/**************************************************************************/

unsigned int omx_file_write(void *buffer, unsigned int nBlock, unsigned int size, omx_file *filehandle)
{
    return fwrite(buffer, nBlock, size, filehandle);
}
void  omx_Dprintf(int n,char *format,...)
{
#if DEBUG_LEVEL
    va_list arg_ptr;
   
    if(DEBUG_LEVEL & (n)){
    va_start(arg_ptr,format);
    vprintf(format, arg_ptr);

    }
#endif    
}

